import cv2
import os
import imagehash
import json
from PIL import Image
# import logging

# # 配置日志
# logging.basicConfig(
#     filename="app.log",
#     level=logging.DEBUG,
#     format="%(asctime)s - %(levelname)s - %(message)s"
# )


opration_lable = None  

def extract_video_fingerprints_by_seconds(video_path, interval_seconds=1):
    """
    每隔指定秒数提取视频的指纹。
    
    :param video_path: 视频文件路径。
    :param interval_seconds: 提取帧的时间间隔（秒）。
    :return: 视频指纹列表，每个元素是 (时间戳, 指纹)。
    """
    fingerprints = []
    cap = cv2.VideoCapture(video_path)
    fps = cap.get(cv2.CAP_PROP_FPS)  # 获取视频帧率
    frame_interval = int(fps * interval_seconds) if int(fps * interval_seconds) > 0 else 1  # 转换为帧数间隔
    frame_count = 0
    video_time = 0  # 当前时间戳
    
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        
        if frame_count % frame_interval == 0:
            # 计算时间戳（秒）
            video_time = frame_count // fps
            # 转换为PIL格式计算感知哈希值
            pil_frame = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
            hash_value = str(imagehash.phash(pil_frame))  # 使用感知哈希
            fingerprints.append((video_time, hash_value))
        
        frame_count += 1
    
    cap.release()
    return fingerprints

def load_or_compute_fingerprints(video_path, cache_path, interval_seconds=1):
    """
    从缓存中加载指纹，若无缓存则计算并保存。
    
    :param video_path: 视频文件路径。
    :param cache_path: 缓存文件路径。
    :param interval_seconds: 提取帧的时间间隔（秒）。
    :return: 视频指纹列表。
    """
    cache_key = os.path.basename(video_path)  # 缓存的键为视频文件名
    if os.path.exists(cache_path):
        with open(cache_path, "r") as cache_file:
            cache_data = json.load(cache_file)
            if cache_key in cache_data:
                # print(f"从缓存加载指纹: {video_path}")
                opration_lable.config(text=f"从缓存加载指纹: {video_path}")
                return cache_data[cache_key]
    
    # print(f"计算指纹: {video_path}")
    opration_lable.config(text=f"计算指纹: {video_path}")

    fingerprints = extract_video_fingerprints_by_seconds(video_path, interval_seconds)
    opration_lable.config(text=f"计算指纹: {video_path}完成！")

    
    # 保存到缓存
    if os.path.exists(cache_path):
        with open(cache_path, "r") as cache_file:
            cache_data = json.load(cache_file)
    else:
        cache_data = {}
    
    cache_data[cache_key] = fingerprints
    with open(cache_path, "w") as cache_file:
        json.dump(cache_data, cache_file)
    
    return fingerprints

def match_fingerprints_by_seconds(long_video_fp, short_videos_fp):
    """
    比较长视频和短视频的指纹，按秒级匹配。
    
    :param long_video_fp: 长视频的指纹列表 [(时间戳, 指纹)]。
    :param short_videos_fp: 短视频指纹字典 {视频名称: [(时间戳, 指纹)]}。
    :return: 匹配结果 {长视频时间戳: (短视频名称, 短视频时间戳)}。
    """
    matches = {}
    for long_time, long_fp in long_video_fp:
        for short_name, short_fps in short_videos_fp.items():
            for short_time, short_fp in short_fps:
                if long_fp == short_fp:
                    matches[long_time] = (short_name, short_time)
                    opration_lable.config(text=f"视频第 {format_time(long_time)}s 来源于: {short_name} 的 {format_time(short_time)}s")
                    break
    return matches

def format_time(seconds):
    """
    将秒转换为 分钟:秒 格式。
    
    :param seconds: 时间戳（秒）。
    :return: 格式化时间字符串。
    """
    total_seconds = int(seconds)  # 转换为整数
    minutes = total_seconds // 60
    secs = total_seconds % 60
    return f"{minutes:02d}分{secs:02d}秒"

def analyze_video_sources_by_seconds(long_video_path, short_videos_dir, cache_path, interval_seconds=1):
    """
    分析长视频的素材来源（精确到秒）。
    
    :param long_video_path: 长视频文件路径。
    :param short_videos_dir: 短视频所在文件夹路径。
    :param cache_path: 指纹缓存文件路径。
    :param interval_seconds: 提取帧的时间间隔（秒）。
    :return: 分析结果。
    """
    # 提取长视频指纹
    # print("提取长视频指纹...")
    opration_lable.config(text=f"提取长视频指纹...")

    long_video_fp = load_or_compute_fingerprints(long_video_path, cache_path, interval_seconds)
    
    # 提取短视频指纹
    # print("提取短视频指纹...")
    opration_lable.config(text=f"提取短视频指纹...")

    short_videos_fp = {}
    for filename in os.listdir(short_videos_dir):
        short_video_path = os.path.join(short_videos_dir, filename)
        if not short_video_path.endswith(('.mp4', '.avi', '.mkv')):
            continue
        short_videos_fp[filename] = load_or_compute_fingerprints(short_video_path, cache_path, interval_seconds)
    
    # 比对指纹
    # print("比对指纹...")
    matches = match_fingerprints_by_seconds(long_video_fp, short_videos_fp)
    
    # 格式化输出
    formatted_matches = {}
    for long_time, (short_name, short_time) in matches.items():
        formatted_matches[format_time(long_time)] = (short_name, format_time(short_time))
    
    return formatted_matches

def group_matches(matches):
    """
    将匹配结果按连续时间段分组。
    
    :param matches: 匹配结果 {长视频时间戳: (短视频名称, 短视频时间戳)}。
    :return: 分组后的匹配结果 [(长视频起始时间, 长视频结束时间, 短视频名称, 短视频起始时间, 短视频结束时间)]。
    """
    grouped_results = []
    current_group = None  # 当前分组 (长视频起始时间, 短视频名称, 短视频起始时间)

    for long_time in sorted(matches.keys()):
        short_name, short_time = matches[long_time]
        if current_group is None:
            # 开始新的分组
            current_group = [long_time, long_time, short_name, short_time, short_time]
        else:
            # 判断是否连续
            if (long_time == current_group[1] + 1 and
                short_name == current_group[2] and
                short_time == current_group[4] + 1):
                # 扩展当前分组
                current_group[1] = long_time
                current_group[4] = short_time
            else:
                # 结束当前分组并保存
                grouped_results.append(tuple(current_group))
                # 开始新的分组
                current_group = [long_time, long_time, short_name, short_time, short_time]
    
    # 保存最后的分组
    if current_group:
        grouped_results.append(tuple(current_group))
    
    return grouped_results

def format_time(seconds):
    """
    将秒转换为 分钟:秒 格式。
    
    :param seconds: 时间戳（秒）。
    :return: 格式化时间字符串。
    """
    total_seconds = int(seconds)  # 转换为整数
    minutes = total_seconds // 60
    secs = total_seconds % 60
    return f"{minutes:02d}分{secs:02d}秒"

def analyze_video_sources_by_seconds(long_video_path, short_videos_dir, cache_path, interval_seconds=1):
    """
    分析长视频的素材来源（精确到秒）。
    
    :param long_video_path: 长视频文件路径。
    :param short_videos_dir: 短视频所在文件夹路径。
    :param cache_path: 指纹缓存文件路径。
    :param interval_seconds: 提取帧的时间间隔（秒）。
    :return: 分析结果。
    """
    # 提取长视频指纹
    # print("提取长视频指纹...")
    opration_lable.config(text=f"提取长视频指纹...")

    long_video_fp = load_or_compute_fingerprints(long_video_path, cache_path, interval_seconds)
    
    # 提取短视频指纹
    # print("提取短视频指纹...")
    opration_lable.config(text=f"提取短视频指纹...")

    short_videos_fp = {}
    for filename in os.listdir(short_videos_dir):
        short_video_path = os.path.join(short_videos_dir, filename)
        if not short_video_path.endswith(('.mp4', '.avi', '.mkv')):
            continue
        short_videos_fp[filename] = load_or_compute_fingerprints(short_video_path, cache_path, interval_seconds)
    
    # 比对指纹
    # print("比对指纹...")
    opration_lable.config(text=f"比对指纹...")
    matches = match_fingerprints_by_seconds(long_video_fp, short_videos_fp)
    
    # 分组连续时间段
    grouped_matches = group_matches(matches)
    
    # 格式化输出
    formatted_results = []
    for long_start, long_end, short_name, short_start, short_end in grouped_matches:
        formatted_results.append(
            f"视频第 {format_time(long_start)} 至第 {format_time(long_end)} 来源于: {short_name} 的 {format_time(short_start)} 至第 {format_time(short_end)}"
        )
    return formatted_results

def list_folders_and_videos(directory):
    folder_paths = []
    video_paths = []
    # 遍历目录下的所有文件和文件夹
    for item in os.listdir(directory):
        item_path = os.path.join(directory, item)
        # 判断是否是文件夹
        if os.path.isdir(item_path):
            folder_paths.append(item_path)
        # 判断是否是视频文件（通过扩展名）
        elif os.path.isfile(item_path) and item.lower().endswith(('.mp4', '.mkv', '.avi', '.mov', '.flv')):
            video_paths.append(item_path)
    return folder_paths[0], video_paths[0]

def save_results_to_file(results, long_video_path):
    """
    将匹配结果保存到一个与长视频同名的 .txt 文件中。
    
    :param results: 匹配结果列表。
    :param long_video_path: 长视频文件路径。
    """
    # 获取长视频文件名（无扩展名）
    long_video_name = long_video_path.rsplit(".", 1)[0]
    print(long_video_name)
    # 生成 .txt 文件路径
    output_file = f"{long_video_name}.txt"

    # 写入文件
    with open(output_file, 'w', encoding='utf-8') as file:
        for result in results:
            file.write(result + "\n")
    # print(f"匹配结果已保存到文件: {output_file}")

#外部程序调用
def getresult(long_video_path,short_videos_dir,result_label):
    
    cache_path = short_videos_dir.rsplit("/", 1)[0] + "/video_fingerprints_cache.json"  # 指纹缓存文件路径
    
    # print(cache_path)

    # print(long_video_path)
    # print(short_videos_dir)

    # 设置提取间隔为1秒
    interval_seconds = 0.02

    global opration_lable 

    opration_lable = result_label

    result_label.config(text="xxxxxxxxx")
    results = analyze_video_sources_by_seconds(long_video_path, short_videos_dir, cache_path, interval_seconds)
    # for result in results:
        # print(result)
    save_results_to_file(results,long_video_path)
    return "结果保存在" + long_video_path.rsplit(".", 1)[0] + ".txt"




# 主程序
# if __name__ == "__main__":
#     """# long_video_path = "./8ea3029cb939ed7009259e63b90edbfb.mp4"  # 替换为你的长视频路径
#     # short_videos_dir = "./4d1bbf49346bab0ea71cda239b793728"  # 替换为短视频所在文件夹路径"""
    
#     current_directory = os.getcwd()
#     short_videos_dir,long_video_path = list_folders_and_videos(current_directory)
#     print(short_videos_dir)
#     print(long_video_path)
    
#     cache_path = "video_fingerprints_cache.json"  # 指纹缓存文件路径
    
#     # 设置提取间隔为1秒
#     interval_seconds = 0.02
    
#     results = analyze_video_sources_by_seconds(long_video_path, short_videos_dir, cache_path, interval_seconds)
#     for result in results:
#         print(result)
#     save_results_to_file(results,long_video_path)
